package com.bianguo.android.camerademo.util;

import android.app.Activity;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.support.annotation.RequiresApi;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.TextureView;

import java.io.File;
import java.io.IOException;

/**
 * Created by Administrator on 2018/3/19.
 */

public class RecorderHelper implements MediaRecorder.OnInfoListener, MediaRecorder.OnErrorListener {

    public static final String VIDEO_DIR = Environment.getExternalStorageDirectory() + "/CameraDemo/Video/";
    private static RecorderHelper mHelper;
    private MediaRecorder mediaRecorder;
    private String outFilePath;
    private OnRecorderListener onRecorderListener;
    private boolean isRecording;
    private Context mContext;

    private static final SparseIntArray DEFAULT_ORIENTATIONS = new SparseIntArray();
    private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray();

    static {
        DEFAULT_ORIENTATIONS.append(Surface.ROTATION_0, 90);
        DEFAULT_ORIENTATIONS.append(Surface.ROTATION_90, 0);
        DEFAULT_ORIENTATIONS.append(Surface.ROTATION_180, 270);
        DEFAULT_ORIENTATIONS.append(Surface.ROTATION_270, 180);
    }

    static {
        INVERSE_ORIENTATIONS.append(Surface.ROTATION_0, 270);
        INVERSE_ORIENTATIONS.append(Surface.ROTATION_90, 180);
        INVERSE_ORIENTATIONS.append(Surface.ROTATION_180, 90);
        INVERSE_ORIENTATIONS.append(Surface.ROTATION_270, 0);
    }

    public boolean isRecording() {
        return isRecording;
    }

    public void setOnRecorderListener(OnRecorderListener onRecorderListener) {
        this.onRecorderListener = onRecorderListener;
    }

    private RecorderHelper(Context mContext) {
        this.mContext = mContext;
//        mediaRecorder = new MediaRecorder();
    }

    public static RecorderHelper getInstance(Context mContext) {
        if (mHelper == null) {
            synchronized (RecorderHelper.class) {
                if (mHelper == null) {
                    mHelper = new RecorderHelper(mContext);
                }
            }
        }
        return mHelper;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void startRecorder(int maxDuration, String outFilePath, TextureView mTextureView, Size mPreviewSize) {
        MLog.mLog("---- startRecorder -----");
        if (mediaRecorder == null) {
            mediaRecorder = new MediaRecorder();
        }
        isRecording = true;
        this.outFilePath = outFilePath;
        mediaRecorder.reset();
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)) {
            CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
            profile.videoBitRate = mPreviewSize.getWidth() * mPreviewSize.getHeight();
            mediaRecorder.setProfile(profile);
            mediaRecorder.setPreviewDisplay(new Surface(mTextureView.getSurfaceTexture()));
        } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)) {
            CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
            profile.videoBitRate = mPreviewSize.getWidth() * mPreviewSize.getHeight();

            mediaRecorder.setProfile(profile);
            mediaRecorder.setPreviewDisplay(new Surface(mTextureView.getSurfaceTexture()));
        } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QVGA)) {
            mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA));
            mediaRecorder.setPreviewDisplay(new Surface(mTextureView.getSurfaceTexture()));
        } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_CIF)) {
            mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_CIF));
            mediaRecorder.setPreviewDisplay(new Surface(mTextureView.getSurfaceTexture()));
        } else {
            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            mediaRecorder.setVideoEncodingBitRate(10000000);
            mediaRecorder.setVideoFrameRate(30);
            mediaRecorder.setVideoEncodingBitRate(2500000);
            mediaRecorder.setVideoFrameRate(20);
            mediaRecorder.setVideoSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        }
        mediaRecorder.setOutputFile(outFilePath);
        mediaRecorder.setMaxDuration(maxDuration);
//        int rotation = ((Activity) mContext).getWindowManager().getDefaultDisplay().getRotation();
//        mediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
        mediaRecorder.setOnInfoListener(this);
        mediaRecorder.setOnErrorListener(this);
        try {
            mediaRecorder.prepare();
            mediaRecorder.start();
        } catch (IOException e) {
            MLog.mLog("startRecorder error : " + e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            MLog.mLog("startRecorder error : " + e.getMessage());
            e.printStackTrace();
        }
    }

    public void stopRecorder() {
        MLog.mLog("---- stopRecorder -----");
        if (mediaRecorder == null) {
            return;
        }
        try {
            mediaRecorder.setOnErrorListener(null);
            mediaRecorder.setOnInfoListener(null);
            mediaRecorder.stop();
            mediaRecorder.reset();
            mediaRecorder.release();
            mediaRecorder = null;

        } catch (Exception e) {
            MLog.mLog("stopRecorder error : " + e.getMessage() + "\n" + e.toString());
//            mediaRecorder.setOnInfoListener(null);
//            mediaRecorder.stop();
//            mediaRecorder.reset();
//            mediaRecorder.release();
//            mediaRecorder = null;
        }
        isRecording = false;
        if (onRecorderListener != null) {
            onRecorderListener.onStop(outFilePath);
        }
    }

    public void cancelRecorder() {
        if (mediaRecorder == null) {
            return;
        }
        mediaRecorder.setOnInfoListener(null);
        mediaRecorder.stop();
        mediaRecorder.reset();
        mediaRecorder.release();
        mediaRecorder = null;
        File file = new File(outFilePath);
        if (file.exists()) {
            file.delete();
        }
        outFilePath = "";
    }

    @Override
    public void onInfo(MediaRecorder mr, int what, int i1) {
        MLog.mLog("MediaRecorder onInfo what = " + what);
        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
            if (mr == mediaRecorder && isRecording) {
                stopRecorder();
            }
        } else if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {

        }
    }

    @Override
    public void onError(MediaRecorder mediaRecorder, int i, int i1) {
        MLog.mLog("MediaRecorder onError what = " + i);
        if (i == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
            stopRecorder();
        }
    }

    public interface OnRecorderListener {

        /**
         * 录音中...
         *
         * @param db   当前声音分贝
         * @param time 录音时长
         */
        void onUpdate(double db, long time);

        /**
         * 停止录音
         *
         * @param filePath 保存路径
         */
        void onStop(String filePath);
    }
}
